﻿using System;
using System.Threading;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;

namespace 垃圾回收器
{
    class Program
    {
        /*
        * 垃圾回收机制：作用是回收不愿再被引用的对象所占用的内存。
        * 垃圾回收只回收内存，不处理其他资源，比如数据库链接，句柄，文件窗口等。。
        * 垃圾回收器根据是否存在任何引用来决定要清理什么，
        * 这暗示垃圾回收处理的是引用对象，只回收堆上的内存
        * 另外，如果要维持对一个对象的引用，就要阻止垃圾回收器重用对象所用的内存 这个就牵扯到了弱引用这个概念了。
        * 
        * 

    系统具有较低的物理内存；

    由托管堆上已分配的对象使用的内存超出了可接受的范围；

    手动调用GC.Collect方法，但几乎所有的情况下，我们都不必调用，因为垃圾回收器会自动调用它，但在上面的例子中，为了体验一下不及时回收垃圾带来的危害，所以手动调用了GC.Collect，大家也可以仔细体会一下运行这个方法带来的不同。

        * 
        * 
        * 
        */
        static void Main(string[] args)
        {
           
            Console.WriteLine("***** Fun with System.GC ****");
            // 输出堆上估计的字节数量
            Console.WriteLine("Estimated bytes on heap: {0}", GC.GetTotalMemory(false));

            Console.WriteLine("最大代数:{0}", GC.MaxGeneration);
            // MaxGeneration是由0开始，因此为了显示的目的加上了1
            Console.WriteLine("This OS has {0} object generations.\n", (GC.MaxGeneration + 1));
            Car refToMyCar = new Car("Zippy", 100);
            Console.WriteLine(refToMyCar.ToString());

            // 输出refToMyCar对象的代
            Console.WriteLine("输出refToMyCar对象的代: {0}",
                GC.GetGeneration(refToMyCar));
            // 只检查第0代对象
            GC.Collect(0);
            //挂起当前线程，直到正在处理的队列的线程终结器清空了队列。
            GC.WaitForPendingFinalizers();
            // Random r = new Random();
            // int[] i = new[] { 1,3,4,5,6,8};
            //r.NextBytes(Convert.ToByte(i[0]),Convert.ToByte(i[3]));
            // r.Next(5,10);
            Console.ReadLine();
        }
    }
    class Car
    {
        // Car的"状态"
        public string petName;
        public int currSpeed;

        // 自定义的默认构造函数
        public Car()
        {
            petName = "Chuck";
            currSpeed = 10;
        }

        // 在这里，currSpeed会获取int的默认值0
        public Car(string pn, int cs)
        {
            petName = pn;
            currSpeed = cs;
        }
    }

    #region CLR via C#
    public static class GCNotification
    {
        //事件字段
        private static Action<Int32> s_gcDone = null;

        public static event Action<Int32> GCDone
        {
            add
            {
                if (s_gcDone == null)
                {
                    new GenObj(0);
                    new GenObj(2);
                }
            }
            remove
            {
                s_gcDone -= value;
            }
        }

        private sealed class GenObj
        {
            private int m_generation;
            public GenObj(Int32 generation)
            {
                m_generation = generation;
            }

            /// <summary>
            /// 终结器
            /// </summary>
            ~GenObj()
            {
                if (GC.GetGeneration(this) >= m_generation)
                {   //通知委托 GC 完成一次
                    Action<Int32> temp = Volatile.Read(ref s_gcDone);
                    if (temp != null) temp(m_generation);
                }
                //如果还存在一个已登记的委托
                if (s_gcDone != null)
                {
                    //如果至少还有一个已登记的委托，而且AppDomain 并非正在卸载，并且进程并非正在关闭就继续
                    if ((m_generation == 0) && !AppDomain.CurrentDomain.IsFinalizingForUnload() && !Environment.HasShutdownStarted)
                    {
                        new GenObj(0);

                    }
                    else
                    {
                        //复活甲
                        GC.ReRegisterForFinalize(this);
                    }
                }
                else
                {

                }
            }
        }

    }


    #region SafeHandle 

    /*
     * 
     */
    class SafeHandleTest : SafeHandle
    {
        public SafeHandleTest(IntPtr invalidHandleValue, bool ownsHandle) : base(invalidHandleValue, ownsHandle)
        {
        }

        /// <summary>
        /// 如果句柄值不代表资源 返回true 
        /// </summary>
        public override bool IsInvalid { get; }

        protected override bool ReleaseHandle()
        {
            throw new NotImplementedException();
        }
    }



    internal static class SomeType
    {
        //声明调用win32 方法 CreateEvent
        [DllImport("Kernel32", CharSet = CharSet.Unicode, EntryPoint = "CreateEvent")]

        //这个原型不健壮
        private static extern IntPtr CreateEventBad(IntPtr cre, Boolean man, Boolean ini, string str);

        [DllImport("Kernel32", CharSet = CharSet.Unicode, EntryPoint = "CreateEvent")]
        private static extern SafeWaitHandle CreateEventGood(IntPtr pse,Boolean man, Boolean ini, string str);//本质上就是调用 win32 方法CreateEvent

        public static void someMethod()
        {
            //直接返回一个句柄对象可能会造成内存泄漏
            IntPtr handle = CreateEventBad(IntPtr.Zero, false, false, null);
            //safehandle 修复了潜在得资源泄露问题
            /*
             * 当 CreateEvent 函数返回到托管代码是，clr 知道 safewaithandle 是派生自 
             * safehandle 所以会在托管堆中构造 safehandle 实例，并向其传递从 CreateEvent
             * 返回得句柄值，这个对象最中会被系统回收掉，总的得来说
             * 所有派生自 safehandle 的对象都是安全的
             * 
             */
            SafeWaitHandle swh =CreateEventGood(handle, false, false,null);

        }
    }

    #endregion




    #endregion
}
